package cn.iocoder.yudao.module.erp.service.pristock;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stocksmove.vo.StocksMoveSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.warehouserule.vo.WarehouseRulePageReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.priaccount.PriAccountDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stocksmove.StocksMoveDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stocksmoveitem.StocksMoveItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehouserule.WarehouseRuleDO;
import cn.iocoder.yudao.module.erp.dal.mysql.priaccount.PriAccountMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stocksmove.StocksMoveMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stocksmoveitem.StocksMoveItemMapper;
import cn.iocoder.yudao.module.erp.service.priaccount.PriAccountService;
import cn.iocoder.yudao.module.erp.service.stocksmove.StocksMoveService;
import cn.iocoder.yudao.module.erp.service.warehouserule.WarehouseRuleService;
import cn.iocoder.yudao.module.erp.service.warehouserule.WarehouseRuleServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.erp.controller.admin.pristock.vo.*;
import cn.iocoder.yudao.module.erp.dal.dataobject.pristock.PriStockDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.erp.dal.mysql.pristock.PriStockMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

/**
 * ERP 一级库库存 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class PriStockServiceImpl implements PriStockService{

    @Resource
    private PriStockMapper priStockMapper;
    @Resource
    private WarehouseRuleService warehouseRuleservice;
//    @Resource
//    private StocksMoveMapper stocksMoveMapper;

    @Resource
    private StocksMoveService stocksMoveService;
    @Resource
    private StocksMoveItemMapper stocksMoveItemMapper;
    @Resource
    private  PriAccountMapper priAccountMapper;
    @Override
    public Long createPriStock(PriStockSaveReqVO createReqVO) {
        // 插入
        PriStockDO priStock = BeanUtils.toBean(createReqVO, PriStockDO.class);
        priStockMapper.insert(priStock);
        // 返回
        return priStock.getId();
    }

    @Override
    public void updatePriStock(PriStockSaveReqVO updateReqVO) {
        // 校验存在
        validatePriStockExists(updateReqVO.getId());
        // 更新
        PriStockDO updateObj = BeanUtils.toBean(updateReqVO, PriStockDO.class);
        priStockMapper.updateById(updateObj);
    }
    public void inupdatePriStock(PriStockSaveReqVO updateReqVO) {
        // 查询是否存在记录
        List<PriStockDO> existingRecords = priStockMapper.selectexist(updateReqVO);

        if (existingRecords != null && !existingRecords.isEmpty()) {
            // 如果记录存在，执行更新操作
            for (PriStockDO existingRecord : existingRecords) {
                // 根据业务逻辑更新记录
                PriStockDO updateObj = BeanUtils.toBean(updateReqVO, PriStockDO.class);
                updateObj.setId(existingRecord.getId()); // 设置要更新的记录的ID

                // 假设 updateReqVO 中有一个字段表示传递过来的数量，比如 count
                // 将字符串转换为整数进行相加
                BigDecimal existingCount = BigDecimal.valueOf(Integer.parseInt(String.valueOf(existingRecord.getCount())));
                BigDecimal updateCount = BigDecimal.valueOf(Integer.parseInt(updateReqVO.getCount()));
                BigDecimal newCountValue = existingCount.add(updateCount) ;

                updateObj.setCount(newCountValue); // 设置新的数量

                priStockMapper.updateById(updateObj);
            }
        } else {
            // 如果记录不存在，执行新增方法
            PriStockDO newObj = BeanUtils.toBean(updateReqVO, PriStockDO.class);
            priStockMapper.insert(newObj);
        }
    }


    // 根据商品id修改
    @Override
    public void updatePriStocks(PriStockSaveReqVO priStockSaveReqVO) {

        priStockMapper.updatePriStocks(priStockSaveReqVO);
    }
    // 根据商品id修改
    @Override  // 取出传递过来的 产品id, 以及减少数量(减少数量为9,不能传递-9)
    public void updatePriStocksdelete(List<PriStockSaveReqVO> priStockSaveReqVO) {
        // 查询出出入库规则
        PageResult <WarehouseRuleDO> warehouseRulePage = warehouseRuleservice.getWarehouseRulePage(new WarehouseRulePageReqVO().setRuleType("0"));
        String rule = warehouseRulePage.getList().stream().map(WarehouseRuleDO::getRule).collect(Collectors.toList()).get(0);
        // 提取出传递进来的参数中所有的商品id到新集合
        List<String> productIds = priStockSaveReqVO.stream()
                .map(PriStockSaveReqVO::getProductId)
                .collect(Collectors.toList());
        List<PriStockDO> kuncun = priStockMapper.selectList(new QueryWrapper<PriStockDO>().in("product_id", productIds));


        // 根据规则进行排序
        if (rule.equals("1")) {
            // 效期优先 (有效期短的优先出库)
            kuncun.sort(Comparator.comparing(PriStockDO::getProductValidityDate));
        } else if (rule.equals("0")) {
            // 先入先出(入库早的数据优先出库)
            kuncun.sort(Comparator.comparing(PriStockDO::getInboundBatch));
        }
        // 根据priStockSaveReqVO中的数量减少kuncun中的数量
        Map<String, String> remainingQuantities = priStockSaveReqVO.stream()
                .collect(Collectors.toMap(PriStockSaveReqVO::getProductId, PriStockSaveReqVO::getCount));

        List<PriStockDO> diaobo = new ArrayList<>();

        for (PriStockDO stock : kuncun) {
            String a =remainingQuantities.get(stock.getProductId().toString());
            Integer remainingQuantity = Integer.valueOf(a);
            if (remainingQuantity != null && remainingQuantity > 0) {
                int quantityToReduce = Math.min(stock.getCount().intValue(), remainingQuantity);
                stock.setCount(stock.getCount().subtract(BigDecimal.valueOf(quantityToReduce)));
                remainingQuantities.put(stock.getProductId().toString(), String.valueOf(remainingQuantity - quantityToReduce));
                PriStockDO diaoboItem = new PriStockDO();
                BeanUtils.copyProperties(stock, diaoboItem);
                diaoboItem.setCount(BigDecimal.valueOf(quantityToReduce));
                if (diaoboItem.getCount().compareTo(BigDecimal.ZERO) != 0 ) {
                    diaobo.add(diaoboItem);
                }

            }
        }

        // 过滤掉 count 等于 0 的记录
        diaobo = diaobo.stream()
                .filter(stock -> stock.getCount().compareTo(BigDecimal.ZERO) > 0)
                .collect(Collectors.toList());

        System.out.println("这个是调拨的数据"+diaobo);
        System.out.println("这个是一级库台账新增的的数据"+diaobo);
        System.out.println("这个是一级库"+kuncun);
        System.out.println("这个是剩余的数据,也就是修改以及库存的数据"+remainingQuantities);
    // 修改一级库存数量
        priStockMapper.updateBatch(kuncun);

// 转换对象并插入数据库
        List<StocksMoveItemDO> stocksMoveItems = diaobo.stream()
                 // 过滤掉 count 等于 0 的记录
                .map(stock -> {
                    StocksMoveItemDO item = new StocksMoveItemDO();
                    item.setProductId(stock.getProductId());
                    item.setProductUnit(stock.getProductUnitId());
                    item.setProductStandards(stock.getProductStandards());
                    item.setProductPrice(stock.getProductPrice());
                    item.setProductBatch(stock.getProductBatch());
                    item.setInboundBatch(stock.getInboundBatch());
                    item.setProductValidityDate(stock.getProductValidityDate());
                    item.setCount(stock.getCount());
                    // 设置其他需要的属性...
                    return item;
                }).collect(Collectors.toList());
        // 创建调拨单对象

        StocksMoveSaveReqVO stocksMove = new StocksMoveSaveReqVO();
        //stocksMove.setNo("生成调拨单号逻辑"); // 设置调拨单号
        stocksMove.setFromWarehouseId(Long.valueOf(kuncun.get(0).getWarehouseId()));
        stocksMove.setToWarehouseId(Long.valueOf(priStockSaveReqVO.get(0).getDeptId()));
        stocksMove.setMoveTime(LocalDateTime.now()); // 设置调拨时间
        //stocksMove.setRemark("调拨备注");
        stocksMove.setStatus(1); // 设置状态
        stocksMove.setStocksMoveItems(stocksMoveItems);
        //过滤掉stocksMoveItems数组下count等于0的数据

        stocksMoveService.createStocksMove(stocksMove);

    //新增一级库台账
        // 将diaobo列表中的PriStockDO对象转换为PriAccountDO对象的列表
        List<PriAccountDO> priAccountList = diaobo.stream().map(stock -> {
            PriAccountDO priAccount = new PriAccountDO();
            // 手动设置PriAccountDO对象的属性值，从PriStockDO对象中获取相应的值
            priAccount.setMainId("一级库分发"); // 设置事务类型（出库、入库、其他）
          // priAccount.setAffairs("your_affairs"); // 设置事务编号
            priAccount.setDeptId(stock.getDeptId()); // 设置单位id
            priAccount.setProductName(stock.getProductName()); // 设置产品名称
            priAccount.setProductId(stock.getProductId().toString()); // 设置产品编号
            priAccount.setProductUnit(stock.getProductUnit()); // 设置产品单位
            priAccount.setProductStandards(stock.getProductStandards()); // 设置产品规格
            priAccount.setProductPrice(stock.getProductPrice()); // 设置产品单价
            priAccount.setProductBatch(stock.getProductBatch()); // 设置批次
            priAccount.setInboundBatch(stock.getInboundBatch()); // 设置入库批次
            priAccount.setProductValidityDate(stock.getProductValidityDate()); // 设置有效期
            priAccount.setCount(stock.getCount().toString()); // 设置数量
            // 设置其他需要的属性...
            return priAccount;
        }).collect(Collectors.toList());
        // 使用批量插入的方法将priAccountList插入到数据库中
        priAccountMapper.insertBatch(priAccountList);
    }

    @Override
    public void deletePriStock(Long id) {
        // 校验存在
        validatePriStockExists(id);
        // 删除
        priStockMapper.deleteById(id);
    }

    private void validatePriStockExists(Long id) {
        if (priStockMapper.selectById(id) == null) {
            throw exception(PRI_STOCK_NOT_EXISTS);
        }
    }

    @Override
    public PriStockDO getPriStock(Long id) {
        return priStockMapper.selectById(id);
    }

    @Override
    public PageResult<PriStockDO> getPriStockPage(PriStockPageReqVO pageReqVO) {
        return priStockMapper.selectPage(pageReqVO);
    }

    @Override
    public List<PriStockRespVO> getPriStockVOList(Collection<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyList();
        }
        List<PriStockDO> list = priStockMapper.selectBatchIds(ids);
        return buildPriStockVOList(list);
    }

    @Override
    public List<PriStockDO> getPriStockList() {
//        return List.of();
        return priStockMapper.selectList();
    }

    @Override
    public List<String> getBatchsByProductId(Long productId) {
        return priStockMapper.selectProductBatchsByProductId(productId);
    }

    @Override
    public PriStockDO getProductByBatch(Long productId, String productBatch) {
        return priStockMapper.selectByProductIdAndBatch(productId, productBatch);
    }

    @Override
    public List<PriStockRespVO> getProductIds() {
        return priStockMapper.selectProductIds();
    }

    @Override
    public void updatePristockCount(PriStockDO productByBatch) {
        priStockMapper.updatePristockCount(productByBatch);
    }

    @Override
    public List<PriStockDO> getProductsByBatch(List<Object> collect) {
        return priStockMapper.selectBatchByBatchs(collect);
    }

    @Override
    public void updatePristockCountBatch(List<PriStockDO> stocksToUpdate) {
        priStockMapper.updatePristockCountBatch(stocksToUpdate);
    }

    @Override
    public List<Integer> getIds() {
        return priStockMapper.selectIds();
    }

    @Override
    public List<String> getStandardsByProductName(String productName) {
        return priStockMapper.selectStandardsByProductName(productName);
    }

    @Override
    public List<String> getInboundBatchsByProductId(Long productId, String productBatch) {
        return priStockMapper.selectInboundBatchsByProductId(productId, productBatch);
    }

    @Override
    public List<PriStockDO> getPriStockListByBatch() {
        return priStockMapper.selectPriListByBatch();
    }

    @Override
    public List<PriStockDO> selectStockListByProductBatch(List<PriStockDO> stocks) {
        return priStockMapper.selectStockListByProductBatch(stocks);
    }

    private List<PriStockRespVO> buildPriStockVOList(List<PriStockDO> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return BeanUtils.toBean(list, PriStockRespVO.class, priStock -> {

        });
    }


}